package org.jaaksi.kottlindemo.generics;

import java.util.ArrayList;
import java.util.List;
import org.jaaksi.kottlindemo.cls.ChildClas;
import org.jaaksi.kottlindemo.cls.ParentClas;
import org.jaaksi.kottlindemo.model.Person;

/**
 * 只能从中读取的对象为生产者（extends），只能写入的对象为消费者（super）
 *
 * <p>out修饰符称为型变注解，并且由于它在类型参数声明处提供，所以我们称之为声明处型变。
 * 这与 Java 的使用处型变相反，其类型用途通配符使得类型协变。</p>
 *
 * <p>另外除了 out，Kotlin 又补充了一个型变注释：in。
 * 它使得一个类型参数逆变：只可以被消费而不可以被生产。
 * 逆变类型的一个很好的例子是 Comparable：</p>
 *
 * <p>在 Java 语言中，数组是协变的。Number[] 也是 Integer[]的超类型。但泛型不是协变的</p>
 *
 * <li>“?”不能添加元素,只能作为生产者(亦即它只能被迭代。可以被赋值)。迭代获取Object
 * <li>“? extends T”也不能添加元素,只能作为生产者。迭代获取T
 * <li>“? super T”能添加元素,所以它能作为消费者（消费其他通配符集合）。迭代只能获取Object
 *
 *
 */
public class TestJava<T> {
  public void fun(List<? extends T> list) {
    T t = list.get(0); // 只能读取T（生产者）
    List<Object> list1 = new ArrayList<>();
    list1.add(1);
    list1.add("1");
    List<?> list2 = new ArrayList<>();
    List<?> list3= new ArrayList<String>();

    //list2.add(1); // 编译错误
    //list3.add("1");// 编译错误
    List<? extends Number> list4 = new ArrayList<>();

//    List<Object> list5 = new ArrayList<String>();
  }

  public void fun(){
    List<Object> object = new ArrayList<>();
    fun2(object);
  }

  public void fun2(List<? super ParentClas> list) {
    Object object = list.get(0); // 无法读取T
    //T t = null;
    list.add(new ChildClas("",1));
  }

}
